package com.xinshujia.config;

import com.xinshujia.config.authentication.filter.JwtAuthenticationTokenFilter;
import com.xinshujia.config.authentication.filter.MyLoginFilter;
import com.xinshujia.config.authentication.handler.MyAuthenticationSuccessHandler;
import com.xinshujia.config.authentication.provider.MyLoginProvider;
import com.xinshujia.config.authentication.service.MyUserDetailsService;
import com.xinshujia.config.authorization.MyAuthorizationManager;
import com.xinshujia.config.authentication.handler.MyAuthenticationFailureHandler;
import com.xinshujia.config.authentication.handler.MyLogoutSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.List;

/**
 * @author: 野狼上校
 * @create: 2023-03-16  10:02
 * @version: 1.0
 * @description:
 */
@Configuration
public class MySecurityConfig {
    /*授权管理器*/
    private final MyAuthorizationManager myAuthorizationManager;
    /*自定义数据库的认证实现*/
    private final MyUserDetailsService myUserDetailsService;
    private final MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    public MySecurityConfig(MyAuthorizationManager myAuthorizationManager, MyUserDetailsService myUserDetailsService, MyAuthenticationSuccessHandler myAuthenticationSuccessHandler, JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter) {
        this.myAuthorizationManager = myAuthorizationManager;
        this.myUserDetailsService = myUserDetailsService;
        this.myAuthenticationSuccessHandler = myAuthenticationSuccessHandler;
        this.jwtAuthenticationTokenFilter = jwtAuthenticationTokenFilter;
    }


    /* 登录认证管理器配置 */
    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(List.of(new MyLoginProvider(myUserDetailsService)));
    }

    /*登录*/
    @Bean
    public MyLoginFilter myLoginFilter(AuthenticationManager authenticationManager) {
        MyLoginFilter myLoginFilter = new MyLoginFilter();
        myLoginFilter.setUsernameParameter("phone");
        myLoginFilter.setPasswordParameter("password");
        myLoginFilter.setFilterProcessesUrl("/login");
        myLoginFilter.setAuthenticationManager(authenticationManager);
        /*认证成功处理器*/
        myLoginFilter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
        /*认证失败处理器*/
        myLoginFilter.setAuthenticationFailureHandler(new MyAuthenticationFailureHandler());
        return myLoginFilter;
    }


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // csrf配置
                .csrf(AbstractHttpConfigurer::disable)
                // cors配置
                .cors(AbstractHttpConfigurer::disable)
                //禁用Session 的机制
                .sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                // 请求拦截
                .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests.anyRequest().access(myAuthorizationManager))
                // 退出
                .logout(logout -> logout.logoutUrl("/logout")
                        .deleteCookies("JSESSIONID")
                        .invalidateHttpSession(true)
                        .logoutSuccessHandler(new MyLogoutSuccessHandler()));
        // Jwt拦截器
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        // 登录拦截器
        httpSecurity.addFilterAt(myLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);

        return httpSecurity.build();
    }

}
